BUSINESS QUESTIONS: Note: ignore the fact there is no question 1, this is due to a formatting error 2. a) Is there are a trend in injuries By Region, and is there different peaks of times of year per region? b) Analysis on the types of animals that are injured, this also by Region – is there a species that is more liable to injury in certain regions? - (cat/dog by region) c) What is the outcome? Does this differ by region?

  1. Total call volume for complaint calls: How has this trended over time?
  2. Is there a particular animal being called about the most?
  3. Do particular suburbs have different type of complaint calls? Do they call about different animals? ((MAKE A LEAFLET MAP FOR THIS!))
  1. Business Intelligence – using the insights you have found, can you predict how this might look for the upcoming year?
source("cleaning_script.R")
Rows: 31330 Columns: 7── Column specification ────────────────────────────────────────────────────────────────
Delimiter: ","
chr (6): nature, animal_type, category, suburb, date_range, city
lgl (1): responsible_office
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.Warning: Expected 2 pieces. Missing pieces filled with `NA` in 5643 rows [7, 11, 12, 18, 19, 25, 27, 29, 30, 31, 39, 44, 52, 54, 66, 67, 74, 75, 78, 81, ...].Rows: 42413 Columns: 5── Column specification ────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): Animal Type, Complaint Type, Date Received, Suburb, Electoral Division
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.Rows: 664 Columns: 12── Column specification ────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (2): animal_type, outcome
dbl (10): year, ACT, NSW, NT, QLD, SA, TAS, VIC, WA, Total
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Note; summer in Australia seasons: Summer: December - February Autumn: March - May Winter: June - August Spring: September - November

also: The ‘wet season’ in Australia’s North: November - April

https://www.mdpi.com/2076-2615/8/7/100 will useful reading for later, talk about the need to reduce euthanasia or similar and the effect this has on people

Intro: Introduce the point of the talk, talk about Australian RSPCA, talk about how the data was gathered (using the information from the websites), the PURPOSE of this investigation (which is to help the RSPCA know which areas/animals to focus their efforts on), as I’m introducing the datasets I can introduce the two different cities. First, we can talk a short bit about Australia as a whole, it’s climate, the kind of animals etc. The point here is to really set the scene before diving too deep into facts and figures, as especially a non-technical audience this will help keep them engaged and make a more holistic presentation. In my opinion, it’s always good to zoom out and see the big picture, rather than getting lost in the myopia of some csv files.

Townsville Intro: Townsville is a city on the north-eastern coast of Queensland, Australia. With a population of 180,820 as of June 2018, it is the largest settlement in North Queensland; it is unofficially considered its capital. [note: put a map of Australia with Queensland and Townsville highlighted here. Talk a little bit about the population density, urbanisation, climate, types of animals that are common here etc. Show some photos of the area too]

Brisbane Intro: Exact same as above

3.

  1. Total call volume for complaint calls: How has this trended over time?

First, let’s look at the Townsville animal complaints.

animal_complaints %>% 
  group_by(date_received) %>% 
  summarise(count = n()) %>% 
  ggplot(aes(x = date_received, y = count)) +
  geom_line() +
  scale_x_date(date_breaks = "6 months", date_labels = "%b-%y")

This shows some seasonality and also an increase then a decline. Each summer (in December) the calls are much lower, rising again each Winter. Using geom_smooth, we get:

animal_complaints %>% 
  group_by(date_received) %>% 
  summarise(count = n()) %>% 
  ggplot(aes(x = date_received, y = count)) +
  geom_smooth() +
  geom_point() +
  scale_x_date(date_breaks = "1 year", date_labels = "%y")

This shows a bit more clearly the general trend of call volume. From 2014 it steadily rises, peaking in 2017. Afterwards, it steadily declines to only slightly higher than where it started. It would be very difficult to say whether this trend will continue downward, go upward or stay relatively flat.

Note; if we have time or if it’s helpful, we will fix this graph so that quarters are properly displayed.

brisbane_complaints %>% 
  group_by(date) %>% 
  summarise(count = n()) %>% 
  ggplot(aes(x = date, y = count)) +
  geom_point() +
  geom_line() +
  scale_x_date(date_breaks = "3 months", date_labels = "%y")

Again, we see the seasonality of winter having more calls. The fact this is in both Brisbane and Townsville suggests a fairly general trend.

brisbane_complaints %>% 
  group_by(date) %>% 
  summarise(count = n()) %>% 
  ggplot(aes(x = date, y = count)) +
  geom_point() +
  geom_smooth() +
  scale_x_date(date_breaks = "1 year", date_labels = "20%y")

Other than declining a little over 2016, the number of calls sees a slow but steady increase towards 2020, being thousands more than it was in 2016 and 2017. So, the general trend is that the RSPCA are getting more complaints as time goes on. Now, this does not necessarily mean the line will continue to go up. We are also missing Q3 from 2016 so this skews the curve a little

3.

  1. Is there a particular animal being called about the most?
animal_complaints %>% 
  group_by(animal_type) %>% 
  ggplot(aes(x = animal_type)) +
  geom_bar()

The number of calls about dogs dwarf those about cats hugely. Let’s look at specific numbers:

animal_complaints %>% 
  group_by(animal_type) %>%
  count() %>% 
  summarise(n, 4094 / 38319)

So cats account for only 10% of the calls dogs do for Townsville! Let’s look at Brisbane:

brisbane_complaints %>% 
  group_by(type_of_animal) %>%
  count()

brisbane_complaints %>% 
  group_by(type_of_animal) %>%
  ggplot(aes(x = type_of_animal)) +
  geom_bar()

We have a lot more animal types here that we don’t in the previous data. We also have many calls about Attacks with no animal specified, many of which it is very likely they were involving dogs. However, we can’t say this for sure.

So that makes

4745 / 13334  # cats are 35% of the calls compared to dogs
[1] 0.3558572
# all other animals divided by dogs, leaving out unspecified (which we believe potentially contain a high proportion of dogs)
9457 / 13349
[1] 0.7084426

Most of the other animals have very small counts, interestingly foxes seem to make up a decent proportion of the calls regarding wild animals.

To answer the question however, it’s mainly dogs and cats, and especially dogs. Dogs are being called about more than any of the other animals combined (if we leave Unspecified to the side)

(Attack refers to the initial description of the complaint)

3.

  1. Do particular suburbs have different type of complaint calls? Do they call about different animals?

OK, so this one is difficult simply for the fact there is a huge amount of suburbs.

brisbane_complaints %>% 
  group_by(suburb) %>% 
  count()

# There is 192 suburbs! Certainly using a fill on a graph is not gonna work, neither is putting them on the x-axis on a bar graph.

animal_complaints %>% 
  group_by(suburb) %>% 
  count()
# 85 suburbs for Townsville

animal_complaints %>% 
  group_by(electoral_division) %>% 
  count()
# also 11 electoral divisions. Could we look at suburbs one electoral division at a time? Possibly

Idea: What about using leaflet to visualise types of complaint calls on a map?

This is more feasible with the Townsville datasets, as it has less suburbs and only 6 types of complaints. It may be necessary to try and wrangle the Brisbane data a little further to narrow down categories (for both type_of_animal and complaint_type)

FOR TOWNSVILLE WE HAVE: 85 different suburbs 6 complaint types 2 animal types

We want to break it down by suburb and complaint type, and then by suburb and animal type

animal_complaints %>% 
  ggplot(aes(x = suburb, fill = animal_type)) +
  geom_bar(position = "fill") +
  coord_flip() +
  scale_x_discrete(guide = guide_axis(n.dodge = 5))

animal_complaints %>% 
  ggplot(aes(x = suburb, fill =complaint_type)) +
  geom_bar(position = "fill") 

  #coord_flip() +
  #scale_x_discrete(guide = guide_axis(n.dodge = 5))

The challenge again, is having too many suburbs that we can’t get any useful information out of the graphs

animal_complaints %>% 
  group_by(suburb) %>% 
  count(sort = TRUE)

# let's drop any suburbs with less than 200 cases

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), animal_type) %>% 
  filter(count >= 500) %>% 
  ggplot(aes(x = suburb, y = count, fill = animal_type)) +
  geom_col() +
  coord_flip()
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

The highest count by quite a large margin is unallocated to a specific suburb.

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), animal_type) %>% 
  filter(count >= 500) %>% 
  ggplot(aes(x = suburb, y = count, fill = animal_type)) +
  geom_col(position = "fill") +
  coord_flip() 
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

At a glance, there’s no big difference on animal types. All the suburbs have a large majority of dogs. Could we do a hypothesis test to see if there is a statistically significant difference?

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), animal_type) %>% 
  filter(count < 500 & count > 100) %>% 
  ggplot(aes(x = suburb, y = count, fill = animal_type)) +
  geom_col(position = "fill") +
  coord_flip() 
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

Looking at the lower end of the population, we see an outlier. Townsville City has way more cats than any of the other suburbs. In fact, it’s almost 50/50!

Now still looking at the Townsville dataset, we’ll break it down by complaint type:

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), complaint_type) %>% 
  filter(count >= 500 & count <= 4000) %>% 
  ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
  geom_col(position = "fill") +
  coord_flip() 
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

Now for the lower end of the count:

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), complaint_type) %>% 
  filter(count < 500 & count > 50) %>% 
  ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
  geom_col(position = "fill") +
  coord_flip() 
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

I’m not sure much can be gleamed with so many complaint_types. Let’s try focusing more specifically.

One thing to note here, is the vast variation in tolerance for noise. Most categories are consistent except this one. Cluden for example has a small percentage of noise complaints,while Bohle Plains has a huge percentage. This requires more investigation to figure out the root cause of this:

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), complaint_type) %>% 
  filter(count >= 500) %>% 
  filter(complaint_type == "Noise" | (complaint_type == "Attack")) %>% 
  ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
  geom_col(position = "fill") +
  coord_flip() 
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), complaint_type) %>% 
  filter(count >= 500) %>% 
  filter(complaint_type == "Noise" | (complaint_type == "Aggressive Animal")) %>% 
  ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
  geom_col(position = "fill") +
  coord_flip() 
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), complaint_type) %>% 
  filter(count >= 500) %>% 
  filter(complaint_type == "Wandering" | (complaint_type == "Aggressive Animal")) %>% 
  ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
  geom_col(position = "fill") +
  coord_flip() 
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), complaint_type) %>% 
  filter(count >= 500) %>% 
  filter(complaint_type == "Enclosure" | (complaint_type == "Noise")) %>% 
  ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
  geom_col(position = "fill") +
  coord_flip() 
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

For the less than 500 greater than 50 groups:

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), complaint_type) %>% 
  filter(count < 500 & count > 100) %>% 
  filter(complaint_type == "Noise" | (complaint_type == "Attack")) %>% 
  ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
  geom_col(position = "fill") +
  coord_flip() 
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), complaint_type) %>% 
  filter(count < 500 & count > 100) %>%  
  filter(complaint_type == "Noise" | (complaint_type == "Aggressive Animal")) %>% 
  ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
  geom_col(position = "fill") +
  coord_flip() 
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), complaint_type) %>% 
  filter(count < 500 & count > 100) %>% 
  filter(complaint_type == "Wandering" | (complaint_type == "Aggressive Animal")) %>% 
  ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
  geom_col(position = "fill") +
  coord_flip() 
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), complaint_type) %>% 
  filter(count < 500 & count > 100) %>% 
  #filter(complaint_type == "Enclosure" | (complaint_type == "Noise")) %>% 
  ggplot(aes(x = suburb, y = count, fill = complaint_type)) +
  geom_col(position = "fill") +
  coord_flip() +
  facet_wrap(~ suburb)
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), complaint_type, animal_type) %>% 
  filter(count < 500 & count > 100) %>% 
  ggplot(aes(x = complaint_type, y = count, fill = complaint_type)) +
  geom_col() +
  facet_wrap(~ suburb)
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

From this graph, we can see that Hyde Park has a disproportionate amount of private impounds, while Bohle plains has more noise complaints.

Potential hypothesis test:

That the level of private impounds in Hyde Park being greater is statistically significant.

That the level of noise in Bohle Plains being greater is statistically significant.

animal_complaints %>% 
  group_by(suburb) %>% 
  count() %>% 
  filter(n < 500 & n > 100)

Let’s look at the suburbs with much higher complaints now:

animal_complaints %>% 
  group_by(suburb) %>% 
  summarise(count = n(), complaint_type, animal_type) %>% 
  filter(count >= 500 & count <4000) %>% 
  ggplot(aes(x = complaint_type, y = count, fill = complaint_type)) +
  geom_col() +
  facet_wrap(~ suburb)
`summarise()` has grouped output by 'suburb'. You can override using the `.groups` argument.

2. a) Are there any major differences between regions?

  1. How do the animal outcomes differ over time?

  2. Are there any noticeable anomalies in the data?

It’s impossible to say if there’s different peaks of times of yer per region, as we only have the data for the year as a whole. Unless we look at Suburb rather than region, and break this down by time. However, I think it’d be good to use the general Autralia (nationwide) data.

Proportions overall by region and by outcome. We can see that in general, regions have pretty similar proportions across all outcomes. This won’t be the case for every year though and trends over time, that’s the more interesting stuff.

This is the same thing as before, but for animal type. Same as before, not much discernible difference between the regions.

Next is just the sum ocurrences. We can see the regions that have way more animals injured/taken in by the RSPCA. This could be a population thing, maybe these regions just have more wildlife populations etc., or even a bigger RSPCA presence leading to more cases.

So, this is the data across time (from 1999-2018), with time on the x-axis and number of occurences on the y. Faceted into graphs based on outcome, with the coloured lines representing different regions.

What can we say about this? Well, QLD has had their transfers go way up since about 2009, and in general looks like an increase in cases for them. NSW had a big spike of Currently In Care around 2004. Euthanisation in general seems to be falling out of favour (which is actually true, the RSPCA tries to do it less for various reasons, one actually being the mental health of the staff and another being lots of euthanisations leads to a negative perception of animal shelters)

Exact same as before, but faceted on animal type rather than outcome.

QLD has had a lot more wildlife cases, steadily climbing since about 2006. NSW has had a big drop in cats recently. Dogs too. Horses have gone up every region it looks like. NT has had a huge spike in cats from 2015-2016.

This one has the same x and y, but is faceted based on region. The coloured lines now represent the outcomes.

WA in 2006 had a big increase in euthanizations. VIC has had theirs steadily decreasing over time, this is reflected also in NSW, TAS and ACT.

Same as before with faceting based on region, but now the coloured lines represent the type of animal the RSPCA is dealing with.

NT has had a big spike in dogs and cats in recent years. WA had a big spike in wildlife in 2005, corresponding with their spike in euthanizations - common sense and domain knowledge tell us these are likely highly correlated. VIC’s numbers in general seem to be decreasing over time.

Looking now specifically at euthanizations, faceted by region with the lines representing euthanizations.

Now we no longer facet by region.

OK so cats and dogs have way less euthanisations. Wildlife has gone way up! Horses are too small a sample to be meaningful. Other animals have spiked then decreased.

Looking at rehomes to euthanisations, we see cats have an upward trend with less euthanisations and more rehomes, with dogs, both have gone down. Perhaps with dogs there’s a confounding factor. In fact, it seems like the RSPCA is dealing with less dogs in general.

Euthanizations for wildlife have overall gone up. Queensland is skewing the data, they’ve euthanized way more! Is this necessarily a bad thing? It could indicate a bigger RSPCA presence in the area, and more vigilance in regards to controlling the wildlife.

General thoughts:

big change in 2006 for WA; cyclone Emma March 2006 could’ve released many wild animals leading to high euthanizations (this for 2.c) different territories have different approaches;

4. Business Intelligence – using the insights you have found, can you predict how this might look for the upcoming year?

animal_outcomes %>% 
  drop_na() %>% 
  group_by(region, outcome, year) %>%
  summarize(total_injuries = sum(number_of_occurences)) %>%
  ungroup() %>% 
  filter(outcome == "Euthanized") %>% 
  ggplot(aes(x = year, y = total_injuries, color = outcome)) +
  geom_line() +
  facet_wrap(~region, scales = "free_y") +
  labs(x = "Date", y = "Number of injuries", color = "Outcome")
`summarise()` has grouped output by 'region', 'outcome'. You can override using the `.groups` argument.

# Load required packages
library(forecast)

# Convert the data to a time series object
ts_data <- ts(euthanized_data$total_occurrences, start = c(1999, 1), frequency = 1)

# Fit an ARIMA model to the time series data
arima_model <- auto.arima(ts_data)

# Make forecasts for the next 5 years
forecast_values <- forecast(arima_model, h = 5)

# Plot the forecasted values and the 95% confidence intervals
plot(forecast_values, xlab = "Year", ylab = "Total Euthanized Occurrences", main = "ARIMA Forecast", xlim = c(1999, 2023))

Creating a model for Townsville Total cases:

library(ggthemes)

animal_complaints %>% 
  group_by(date_received) %>% 
  summarise(count = n()) %>% 
  ggplot() +
  aes(x = date_received, y = count ) +
  geom_line(col = "blue") +
  scale_x_date(date_breaks = "6 months", date_labels = "%b %y") + 
  labs(title = "Townsville Complaint Calls",
       x = "Time",
       y = "Number of Calls") +
  theme_economist() +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, family = "mono", face = "bold", size = 7),
        axis.title.y = element_text(vjust = 3.2),
        title = element_text(family = "mono", face = "bold"),
        plot.title = element_text(hjust = 0.4)) +
        annotate("rect", xmin = as.Date("2014-06-01"), xmax = as.Date("2014-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
        annotate("rect", xmin = as.Date("2015-06-01"), xmax = as.Date("2015-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
        annotate("rect", xmin = as.Date("2016-06-01"), xmax = as.Date("2016-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
        annotate("rect", xmin = as.Date("2017-06-01"), xmax = as.Date("2017-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
        annotate("rect", xmin = as.Date("2018-06-01"), xmax = as.Date("2018-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3) +
        annotate("rect", xmin = as.Date("2019-06-01"), xmax = as.Date("2019-08-01"), ymin = -Inf, ymax = Inf, fill = "gray70", alpha = 0.3)

this sorta works:

library(tidyverse)
library(forecast)
library(ggthemes)


# Create a time series from the data
animal_complaints_ts <- animal_complaints %>%
  group_by(date_received) %>%
  summarise(count = n()) %>%
  ts(frequency = 365)

# Forecasting for next 3 years
animal_complaints_fc <- forecast(animal_complaints_ts, h = 3*365)
Error in UseMethod("forecast") : 
  no applicable method for 'forecast' applied to an object of class "c('mts', 'ts', 'matrix')"
library(forecast)
library(ggthemes)

# Convert the date_received column to a Date type

# Aggregate the data to get the count of complaints per day
animal_complaints <- animal_complaints %>% 
  group_by(date_received) %>% 
  summarise(count = n()) %>% 
  ungroup()

# Convert the data to a time series object
ts_data <- ts(animal_complaints$count, frequency = 365)

# Decompose the time series using STL
ts_stl <- stl(ts_data, s.window = "periodic")
Error in stl(ts_data, s.window = "periodic") : 
  series is not periodic or has less than two periods
# Create a time series with a frequency of 12 (monthly data)
ts_data <- ts(animal_complaints$count, frequency = 12)

# Fit a seasonal ARIMA model to the time series
fit <- auto.arima(ts_data)

# Forecast the next 36 periods (3 years)
forecast_values <- forecast(fit, h = 36)
Error in switch(names(interval), day = "days", hour = "hours", minute = "mins",  : 
  EXPR must be a length 1 vector
ts_data <- ts(data, start = c(2014, 1), frequency = 12)
Error in attr(data, "tsp") <- c(start, end, frequency) : 
  object is not a matrix
library(forecast)

ts_data <- animal_complaints %>% 
  group_by(date_received) %>% 
  summarise(count = n()) %>% 
  as.data.frame() %>% 
  as.matrix.data.frame()

ts_data <- ts(ts_data, start = c(2014,1), frequency = 12)

fit <- auto.arima(ts_data)
Error in auto.arima(ts_data) : 
  auto.arima can only handle univariate time series
forecast_values <- forecast(fit, h = 36)
Error in switch(names(interval), day = "days", hour = "hours", minute = "mins",  : 
  EXPR must be a length 1 vector
LS0tCnRpdGxlOiAiQW5hbHlzaXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCkJVU0lORVNTIFFVRVNUSU9OUzoKTm90ZTogaWdub3JlIHRoZSBmYWN0IHRoZXJlIGlzIG5vIHF1ZXN0aW9uIDEsIHRoaXMgaXMgZHVlIHRvIGEgZm9ybWF0dGluZyBlcnJvcgoyLiAKYSkgSXMgdGhlcmUgYXJlIGEgdHJlbmQgaW4gaW5qdXJpZXMgQnkgUmVnaW9uLCBhbmQgaXMgdGhlcmUgZGlmZmVyZW50IHBlYWtzIG9mIHRpbWVzIG9mIHllYXIgcGVyIHJlZ2lvbj8KYikgQW5hbHlzaXMgb24gdGhlIHR5cGVzIG9mIGFuaW1hbHMgdGhhdCBhcmUgaW5qdXJlZCwgdGhpcyBhbHNvIGJ5IFJlZ2lvbiDigJMgaXMgdGhlcmUgYSBzcGVjaWVzIHRoYXQgaXMgbW9yZSBsaWFibGUgdG8gaW5qdXJ5IGluIGNlcnRhaW4gcmVnaW9ucz8gLSAoY2F0L2RvZyBieSByZWdpb24pCmMpIFdoYXQgaXMgdGhlIG91dGNvbWU/IERvZXMgdGhpcyBkaWZmZXIgYnkgcmVnaW9uPwoKMy4KYSkgVG90YWwgY2FsbCB2b2x1bWUgZm9yIGNvbXBsYWludCBjYWxsczogSG93IGhhcyB0aGlzIHRyZW5kZWQgb3ZlciB0aW1lPwpiKSBJcyB0aGVyZSBhIHBhcnRpY3VsYXIgYW5pbWFsIGJlaW5nIGNhbGxlZCBhYm91dCB0aGUgbW9zdD8KYykgRG8gcGFydGljdWxhciBzdWJ1cmJzIGhhdmUgZGlmZmVyZW50IHR5cGUgb2YgY29tcGxhaW50IGNhbGxzPyBEbyB0aGV5IGNhbGwgYWJvdXQgZGlmZmVyZW50IGFuaW1hbHM/ICgoTUFLRSBBIExFQUZMRVQgTUFQIEZPUiBUSElTISkpCgo0LgpCdXNpbmVzcyBJbnRlbGxpZ2VuY2Ug4oCTIHVzaW5nIHRoZSBpbnNpZ2h0cyB5b3UgaGF2ZSBmb3VuZCwgY2FuIHlvdSBwcmVkaWN0IGhvdyB0aGlzIG1pZ2h0IGxvb2sgZm9yIHRoZSB1cGNvbWluZyB5ZWFyPwoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHRzaWJibGUpCmxpYnJhcnkoZm9yZWNhc3QpCnNvdXJjZSgiY2xlYW5pbmdfc2NyaXB0LlIiKQpgYGAKCk5vdGU7IHN1bW1lciBpbiBBdXN0cmFsaWEgc2Vhc29uczoKU3VtbWVyOiBEZWNlbWJlciAtIEZlYnJ1YXJ5CkF1dHVtbjogTWFyY2ggLSBNYXkKV2ludGVyOiBKdW5lIC0gQXVndXN0ClNwcmluZzogU2VwdGVtYmVyIC0gTm92ZW1iZXIKCmFsc286IFRoZSAnd2V0IHNlYXNvbicgaW4gQXVzdHJhbGlhJ3MgTm9ydGg6IE5vdmVtYmVyIC0gQXByaWwKCmh0dHBzOi8vd3d3Lm1kcGkuY29tLzIwNzYtMjYxNS84LzcvMTAwICAgd2lsbCB1c2VmdWwgcmVhZGluZyBmb3IgbGF0ZXIsIHRhbGsgYWJvdXQgdGhlIG5lZWQgdG8gcmVkdWNlIGV1dGhhbmFzaWEgb3Igc2ltaWxhciBhbmQgdGhlIGVmZmVjdCB0aGlzIGhhcyBvbiBwZW9wbGUKCkludHJvOgpJbnRyb2R1Y2UgdGhlIHBvaW50IG9mIHRoZSB0YWxrLCB0YWxrIGFib3V0IEF1c3RyYWxpYW4gUlNQQ0EsIHRhbGsgYWJvdXQgaG93IHRoZSBkYXRhIHdhcyBnYXRoZXJlZCAodXNpbmcgdGhlIGluZm9ybWF0aW9uIGZyb20gdGhlIHdlYnNpdGVzKSwgdGhlIFBVUlBPU0Ugb2YgdGhpcyBpbnZlc3RpZ2F0aW9uICh3aGljaCBpcyB0byBoZWxwIHRoZSBSU1BDQSBrbm93IHdoaWNoIGFyZWFzL2FuaW1hbHMgdG8gZm9jdXMgdGhlaXIgZWZmb3J0cyBvbiksIGFzIEknbSBpbnRyb2R1Y2luZyB0aGUgZGF0YXNldHMgSSBjYW4gaW50cm9kdWNlIHRoZSB0d28gZGlmZmVyZW50IGNpdGllcy4gRmlyc3QsIHdlIGNhbiB0YWxrIGEgc2hvcnQgYml0IGFib3V0IEF1c3RyYWxpYSBhcyBhIHdob2xlLCBpdCdzIGNsaW1hdGUsIHRoZSBraW5kIG9mIGFuaW1hbHMgZXRjLiBUaGUgcG9pbnQgaGVyZSBpcyB0byByZWFsbHkgc2V0IHRoZSBzY2VuZSBiZWZvcmUgZGl2aW5nIHRvbyBkZWVwIGludG8gZmFjdHMgYW5kIGZpZ3VyZXMsIGFzIGVzcGVjaWFsbHkgYSBub24tdGVjaG5pY2FsIGF1ZGllbmNlIHRoaXMgd2lsbCBoZWxwIGtlZXAgdGhlbSBlbmdhZ2VkIGFuZCBtYWtlIGEgbW9yZSBob2xpc3RpYyBwcmVzZW50YXRpb24uIEluIG15IG9waW5pb24sIGl0J3MgYWx3YXlzIGdvb2QgdG8gem9vbSBvdXQgYW5kIHNlZSB0aGUgYmlnIHBpY3R1cmUsIHJhdGhlciB0aGFuIGdldHRpbmcgbG9zdCBpbiB0aGUgbXlvcGlhIG9mIHNvbWUgY3N2IGZpbGVzLgoKVG93bnN2aWxsZSBJbnRybzoKVG93bnN2aWxsZSBpcyBhIGNpdHkgb24gdGhlIG5vcnRoLWVhc3Rlcm4gY29hc3Qgb2YgUXVlZW5zbGFuZCwgQXVzdHJhbGlhLiBXaXRoIGEgcG9wdWxhdGlvbiBvZiAxODAsODIwIGFzIG9mIEp1bmUgMjAxOCwgaXQgaXMgdGhlIGxhcmdlc3Qgc2V0dGxlbWVudCBpbiBOb3J0aCBRdWVlbnNsYW5kOyBpdCBpcyB1bm9mZmljaWFsbHkgY29uc2lkZXJlZCBpdHMgY2FwaXRhbC4gW25vdGU6IHB1dCBhIG1hcCBvZiBBdXN0cmFsaWEgd2l0aCBRdWVlbnNsYW5kIGFuZCBUb3duc3ZpbGxlIGhpZ2hsaWdodGVkIGhlcmUuIFRhbGsgYSBsaXR0bGUgYml0IGFib3V0IHRoZSBwb3B1bGF0aW9uIGRlbnNpdHksIHVyYmFuaXNhdGlvbiwgY2xpbWF0ZSwgdHlwZXMgb2YgYW5pbWFscyB0aGF0IGFyZSBjb21tb24gaGVyZSBldGMuIFNob3cgc29tZSBwaG90b3Mgb2YgdGhlIGFyZWEgdG9vXQoKQnJpc2JhbmUgSW50cm86CkV4YWN0IHNhbWUgYXMgYWJvdmUKCiMjIyAzLgphKSBUb3RhbCBjYWxsIHZvbHVtZSBmb3IgY29tcGxhaW50IGNhbGxzOiBIb3cgaGFzIHRoaXMgdHJlbmRlZCBvdmVyIHRpbWU/CgpGaXJzdCwgbGV0J3MgbG9vayBhdCB0aGUgVG93bnN2aWxsZSBhbmltYWwgY29tcGxhaW50cy4KYGBge3J9CmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShkYXRlX3JlY2VpdmVkKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZV9yZWNlaXZlZCwgeSA9IGNvdW50KSkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiNiBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIlYi0leSIpCmBgYApUaGlzIHNob3dzIHNvbWUgc2Vhc29uYWxpdHkgYW5kIGFsc28gYW4gaW5jcmVhc2UgdGhlbiBhIGRlY2xpbmUuIEVhY2ggc3VtbWVyIChpbiBEZWNlbWJlcikgdGhlIGNhbGxzIGFyZSBtdWNoIGxvd2VyLCByaXNpbmcgYWdhaW4gZWFjaCBXaW50ZXIuIFVzaW5nIGdlb21fc21vb3RoLCB3ZSBnZXQ6CgpgYGB7cn0KYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KGRhdGVfcmVjZWl2ZWQpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkYXRlX3JlY2VpdmVkLCB5ID0gY291bnQpKSArCiAgZ2VvbV9zbW9vdGgoKSArCiAgZ2VvbV9wb2ludCgpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwgZGF0ZV9sYWJlbHMgPSAiJXkiKQpgYGAKClRoaXMgc2hvd3MgYSBiaXQgbW9yZSBjbGVhcmx5IHRoZSBnZW5lcmFsIHRyZW5kIG9mIGNhbGwgdm9sdW1lLiBGcm9tIDIwMTQgaXQgc3RlYWRpbHkgcmlzZXMsIHBlYWtpbmcgaW4gMjAxNy4gQWZ0ZXJ3YXJkcywgaXQgc3RlYWRpbHkgZGVjbGluZXMgdG8gb25seSBzbGlnaHRseSBoaWdoZXIgdGhhbiB3aGVyZSBpdCBzdGFydGVkLiBJdCB3b3VsZCBiZSB2ZXJ5IGRpZmZpY3VsdCB0byBzYXkgd2hldGhlciB0aGlzIHRyZW5kIHdpbGwgY29udGludWUgZG93bndhcmQsIGdvIHVwd2FyZCBvciBzdGF5IHJlbGF0aXZlbHkgZmxhdC4KCgoKCgoKCk5vdGU7IGlmIHdlIGhhdmUgdGltZSBvciBpZiBpdCdzIGhlbHBmdWwsIHdlIHdpbGwgZml4IHRoaXMgZ3JhcGggc28gdGhhdCBxdWFydGVycyBhcmUgcHJvcGVybHkgZGlzcGxheWVkLgpgYGB7cn0KYnJpc2JhbmVfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSBjb3VudCkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMyBtb250aHMiLCBkYXRlX2xhYmVscyA9ICIleSIpCmBgYAoKQWdhaW4sIHdlIHNlZSB0aGUgc2Vhc29uYWxpdHkgb2Ygd2ludGVyIGhhdmluZyBtb3JlIGNhbGxzLiBUaGUgZmFjdCB0aGlzIGlzIGluIGJvdGggQnJpc2JhbmUgYW5kIFRvd25zdmlsbGUgc3VnZ2VzdHMgYSBmYWlybHkgZ2VuZXJhbCB0cmVuZC4KCmBgYHtyfQpicmlzYmFuZV9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShkYXRlKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IGNvdW50KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgoKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjEgeWVhciIsIGRhdGVfbGFiZWxzID0gIjIwJXkiKQpgYGAKCk90aGVyIHRoYW4gZGVjbGluaW5nIGEgbGl0dGxlIG92ZXIgMjAxNiwgdGhlIG51bWJlciBvZiBjYWxscyBzZWVzIGEgc2xvdyBidXQgc3RlYWR5IGluY3JlYXNlIHRvd2FyZHMgMjAyMCwgYmVpbmcgdGhvdXNhbmRzIG1vcmUgdGhhbiBpdCB3YXMgaW4gMjAxNiBhbmQgMjAxNy4gU28sIHRoZSBnZW5lcmFsIHRyZW5kIGlzIHRoYXQgdGhlIFJTUENBIGFyZSBnZXR0aW5nIG1vcmUgY29tcGxhaW50cyBhcyB0aW1lIGdvZXMgb24uIE5vdywgdGhpcyBkb2VzIG5vdCBuZWNlc3NhcmlseSBtZWFuIHRoZSBsaW5lIHdpbGwgY29udGludWUgdG8gZ28gdXAuIFdlIGFyZSBhbHNvIG1pc3NpbmcgUTMgZnJvbSAyMDE2IHNvIHRoaXMgc2tld3MgdGhlIGN1cnZlIGEgbGl0dGxlCgoKCiMjIyAzLgpiKSBJcyB0aGVyZSBhIHBhcnRpY3VsYXIgYW5pbWFsIGJlaW5nIGNhbGxlZCBhYm91dCB0aGUgbW9zdD8KCmBgYHtyfQphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoYW5pbWFsX3R5cGUpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBhbmltYWxfdHlwZSkpICsKICBnZW9tX2JhcigpCmBgYAoKVGhlIG51bWJlciBvZiBjYWxscyBhYm91dCBkb2dzIGR3YXJmIHRob3NlIGFib3V0IGNhdHMgaHVnZWx5LiBMZXQncyBsb29rIGF0IHNwZWNpZmljIG51bWJlcnM6CmBgYHtyfQphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoYW5pbWFsX3R5cGUpICU+JQogIGNvdW50KCkgJT4lIAogIHN1bW1hcmlzZShuLCA0MDk0IC8gMzgzMTkpCmBgYAoKU28gY2F0cyBhY2NvdW50IGZvciBvbmx5IDEwJSBvZiB0aGUgY2FsbHMgZG9ncyBkbyBmb3IgVG93bnN2aWxsZSEgTGV0J3MgbG9vayBhdCBCcmlzYmFuZToKCmBgYHtyfQpicmlzYmFuZV9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieSh0eXBlX29mX2FuaW1hbCkgJT4lCiAgY291bnQoKQoKYnJpc2JhbmVfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkodHlwZV9vZl9hbmltYWwpICU+JQogIGdncGxvdChhZXMoeCA9IHR5cGVfb2ZfYW5pbWFsKSkgKwogIGdlb21fYmFyKCkKYGBgCgpXZSBoYXZlIGEgbG90IG1vcmUgYW5pbWFsIHR5cGVzIGhlcmUgdGhhdCB3ZSBkb24ndCBpbiB0aGUgcHJldmlvdXMgZGF0YS4gV2UgYWxzbyBoYXZlIG1hbnkgY2FsbHMgYWJvdXQgQXR0YWNrcyB3aXRoIG5vIGFuaW1hbCBzcGVjaWZpZWQsIG1hbnkgb2Ygd2hpY2ggaXQgaXMgdmVyeSBsaWtlbHkgdGhleSB3ZXJlIGludm9sdmluZyBkb2dzLiBIb3dldmVyLCB3ZSBjYW4ndCBzYXkgdGhpcyBmb3Igc3VyZS4KClNvIHRoYXQgbWFrZXMgCmBgYHtyfQo0NzQ1IC8gMTMzMzQgICMgY2F0cyBhcmUgMzUlIG9mIHRoZSBjYWxscyBjb21wYXJlZCB0byBkb2dzCgoKCiMgYWxsIG90aGVyIGFuaW1hbHMgZGl2aWRlZCBieSBkb2dzLCBsZWF2aW5nIG91dCB1bnNwZWNpZmllZCAod2hpY2ggd2UgYmVsaWV2ZSBwb3RlbnRpYWxseSBjb250YWluIGEgaGlnaCBwcm9wb3J0aW9uIG9mIGRvZ3MpCjk0NTcgLyAxMzM0OQpgYGAKCk1vc3Qgb2YgdGhlIG90aGVyIGFuaW1hbHMgaGF2ZSB2ZXJ5IHNtYWxsIGNvdW50cywgaW50ZXJlc3RpbmdseSBmb3hlcyBzZWVtIHRvIG1ha2UgdXAgYSBkZWNlbnQgcHJvcG9ydGlvbiBvZiB0aGUgY2FsbHMgcmVnYXJkaW5nIHdpbGQgYW5pbWFscy4KClRvIGFuc3dlciB0aGUgcXVlc3Rpb24gaG93ZXZlciwgaXQncyBtYWlubHkgZG9ncyBhbmQgY2F0cywgYW5kIGVzcGVjaWFsbHkgZG9ncy4gRG9ncyBhcmUgYmVpbmcgY2FsbGVkIGFib3V0IG1vcmUgdGhhbiBhbnkgb2YgdGhlIG90aGVyIGFuaW1hbHMgY29tYmluZWQgKGlmIHdlIGxlYXZlIFVuc3BlY2lmaWVkIHRvIHRoZSBzaWRlKQoKKEF0dGFjayByZWZlcnMgdG8gdGhlIGluaXRpYWwgZGVzY3JpcHRpb24gb2YgdGhlIGNvbXBsYWludCkKCgojIyMgMy4gCmMpIERvIHBhcnRpY3VsYXIgc3VidXJicyBoYXZlIGRpZmZlcmVudCB0eXBlIG9mIGNvbXBsYWludCBjYWxscz8gRG8gdGhleSBjYWxsIGFib3V0IGRpZmZlcmVudCBhbmltYWxzPwoKT0ssIHNvIHRoaXMgb25lIGlzIGRpZmZpY3VsdCBzaW1wbHkgZm9yIHRoZSBmYWN0IHRoZXJlIGlzIGEgaHVnZSBhbW91bnQgb2Ygc3VidXJicy4KYGBge3J9CmJyaXNiYW5lX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIGNvdW50KCkKCiMgVGhlcmUgaXMgMTkyIHN1YnVyYnMhIENlcnRhaW5seSB1c2luZyBhIGZpbGwgb24gYSBncmFwaCBpcyBub3QgZ29ubmEgd29yaywgbmVpdGhlciBpcyBwdXR0aW5nIHRoZW0gb24gdGhlIHgtYXhpcyBvbiBhIGJhciBncmFwaC4KCmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShzdWJ1cmIpICU+JSAKICBjb3VudCgpCiMgODUgc3VidXJicyBmb3IgVG93bnN2aWxsZQoKYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KGVsZWN0b3JhbF9kaXZpc2lvbikgJT4lIAogIGNvdW50KCkKIyBhbHNvIDExIGVsZWN0b3JhbCBkaXZpc2lvbnMuIENvdWxkIHdlIGxvb2sgYXQgc3VidXJicyBvbmUgZWxlY3RvcmFsIGRpdmlzaW9uIGF0IGEgdGltZT8gUG9zc2libHkKYGBgCgpJZGVhOiBXaGF0IGFib3V0IHVzaW5nIGxlYWZsZXQgdG8gdmlzdWFsaXNlIHR5cGVzIG9mIGNvbXBsYWludCBjYWxscyBvbiBhIG1hcD8KClRoaXMgaXMgbW9yZSBmZWFzaWJsZSB3aXRoIHRoZSBUb3duc3ZpbGxlIGRhdGFzZXRzLCBhcyBpdCBoYXMgbGVzcyBzdWJ1cmJzIGFuZCBvbmx5IDYgdHlwZXMgb2YgY29tcGxhaW50cy4gSXQgbWF5IGJlIG5lY2Vzc2FyeSB0byB0cnkgYW5kIHdyYW5nbGUgdGhlIEJyaXNiYW5lIGRhdGEgYSBsaXR0bGUgZnVydGhlciB0byBuYXJyb3cgZG93biBjYXRlZ29yaWVzIChmb3IgYm90aCB0eXBlX29mX2FuaW1hbCBhbmQgY29tcGxhaW50X3R5cGUpCgpGT1IgVE9XTlNWSUxMRSBXRSBIQVZFOgo4NSBkaWZmZXJlbnQgc3VidXJicwo2IGNvbXBsYWludCB0eXBlcwoyIGFuaW1hbCB0eXBlcwoKV2Ugd2FudCB0byBicmVhayBpdCBkb3duIGJ5IHN1YnVyYiBhbmQgY29tcGxhaW50IHR5cGUsIGFuZCB0aGVuIGJ5IHN1YnVyYiBhbmQgYW5pbWFsIHR5cGUKYGBge3J9CmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzdWJ1cmIsIGZpbGwgPSBhbmltYWxfdHlwZSkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKwogIGNvb3JkX2ZsaXAoKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShndWlkZSA9IGd1aWRlX2F4aXMobi5kb2RnZSA9IDUpKQpgYGAKCmBgYHtyfQphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc3VidXJiLCBmaWxsID1jb21wbGFpbnRfdHlwZSkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgCiAgI2Nvb3JkX2ZsaXAoKSArCiAgI3NjYWxlX3hfZGlzY3JldGUoZ3VpZGUgPSBndWlkZV9heGlzKG4uZG9kZ2UgPSA1KSkKYGBgCgpUaGUgY2hhbGxlbmdlIGFnYWluLCBpcyBoYXZpbmcgdG9vIG1hbnkgc3VidXJicyB0aGF0IHdlIGNhbid0IGdldCBhbnkgdXNlZnVsIGluZm9ybWF0aW9uIG91dCBvZiB0aGUgZ3JhcGhzCgpgYGB7cn0KYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIGNvdW50KHNvcnQgPSBUUlVFKQoKIyBsZXQncyBkcm9wIGFueSBzdWJ1cmJzIHdpdGggbGVzcyB0aGFuIDIwMCBjYXNlcwoKYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgYW5pbWFsX3R5cGUpICU+JSAKICBmaWx0ZXIoY291bnQgPj0gNTAwKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc3VidXJiLCB5ID0gY291bnQsIGZpbGwgPSBhbmltYWxfdHlwZSkpICsKICBnZW9tX2NvbCgpICsKICBjb29yZF9mbGlwKCkKYGBgCgpUaGUgaGlnaGVzdCBjb3VudCBieSBxdWl0ZSBhIGxhcmdlIG1hcmdpbiBpcyB1bmFsbG9jYXRlZCB0byBhIHNwZWNpZmljIHN1YnVyYi4KCmBgYHtyfQphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoc3VidXJiKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCBhbmltYWxfdHlwZSkgJT4lIAogIGZpbHRlcihjb3VudCA+PSA1MDApICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzdWJ1cmIsIHkgPSBjb3VudCwgZmlsbCA9IGFuaW1hbF90eXBlKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKSArCiAgY29vcmRfZmxpcCgpIApgYGAKQXQgYSBnbGFuY2UsIHRoZXJlJ3Mgbm8gYmlnIGRpZmZlcmVuY2Ugb24gYW5pbWFsIHR5cGVzLiBBbGwgdGhlIHN1YnVyYnMgaGF2ZSBhIGxhcmdlIG1ham9yaXR5IG9mIGRvZ3MuIENvdWxkIHdlIGRvIGEgaHlwb3RoZXNpcyB0ZXN0IHRvIHNlZSBpZiB0aGVyZSBpcyBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZT8KCmBgYHtyfQphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoc3VidXJiKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCBhbmltYWxfdHlwZSkgJT4lIAogIGZpbHRlcihjb3VudCA8IDUwMCAmIGNvdW50ID4gMTAwKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc3VidXJiLCB5ID0gY291bnQsIGZpbGwgPSBhbmltYWxfdHlwZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJmaWxsIikgKwogIGNvb3JkX2ZsaXAoKSAKYGBgCkxvb2tpbmcgYXQgdGhlIGxvd2VyIGVuZCBvZiB0aGUgcG9wdWxhdGlvbiwgd2Ugc2VlIGFuIG91dGxpZXIuIFRvd25zdmlsbGUgQ2l0eSBoYXMgd2F5IG1vcmUgY2F0cyB0aGFuIGFueSBvZiB0aGUgb3RoZXIgc3VidXJicy4gSW4gZmFjdCwgaXQncyBhbG1vc3QgNTAvNTAhCgpOb3cgc3RpbGwgbG9va2luZyBhdCB0aGUgVG93bnN2aWxsZSBkYXRhc2V0LCB3ZSdsbCBicmVhayBpdCBkb3duIGJ5IGNvbXBsYWludCB0eXBlOgpgYGB7cn0KYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgY29tcGxhaW50X3R5cGUpICU+JSAKICBmaWx0ZXIoY291bnQgPj0gNTAwICYgY291bnQgPD0gNDAwMCkgJT4lIAogIGdncGxvdChhZXMoeCA9IHN1YnVyYiwgeSA9IGNvdW50LCBmaWxsID0gY29tcGxhaW50X3R5cGUpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZmlsbCIpICsKICBjb29yZF9mbGlwKCkgCmBgYAoKTm93IGZvciB0aGUgbG93ZXIgZW5kIG9mIHRoZSBjb3VudDoKYGBge3J9CmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShzdWJ1cmIpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCksIGNvbXBsYWludF90eXBlKSAlPiUgCiAgZmlsdGVyKGNvdW50IDwgNTAwICYgY291bnQgPiA1MCkgJT4lIAogIGdncGxvdChhZXMoeCA9IHN1YnVyYiwgeSA9IGNvdW50LCBmaWxsID0gY29tcGxhaW50X3R5cGUpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZmlsbCIpICsKICBjb29yZF9mbGlwKCkgCmBgYAoKSSdtIG5vdCBzdXJlIG11Y2ggY2FuIGJlIGdsZWFtZWQgd2l0aCBzbyBtYW55IGNvbXBsYWludF90eXBlcy4gTGV0J3MgdHJ5IGZvY3VzaW5nIG1vcmUgc3BlY2lmaWNhbGx5LgoKT25lIHRoaW5nIHRvIG5vdGUgaGVyZSwgaXMgdGhlIHZhc3QgdmFyaWF0aW9uIGluIHRvbGVyYW5jZSBmb3Igbm9pc2UuIE1vc3QgY2F0ZWdvcmllcyBhcmUgY29uc2lzdGVudCBleGNlcHQgdGhpcyBvbmUuIENsdWRlbiBmb3IgZXhhbXBsZSBoYXMgYSBzbWFsbCBwZXJjZW50YWdlIG9mIG5vaXNlIGNvbXBsYWludHMsd2hpbGUgQm9obGUgUGxhaW5zIGhhcyBhIGh1Z2UgcGVyY2VudGFnZS4gVGhpcyByZXF1aXJlcyBtb3JlIGludmVzdGlnYXRpb24gdG8gZmlndXJlIG91dCB0aGUgcm9vdCBjYXVzZSBvZiB0aGlzOiAKCmBgYHtyfQphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoc3VidXJiKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCBjb21wbGFpbnRfdHlwZSkgJT4lIAogIGZpbHRlcihjb3VudCA+PSA1MDApICU+JSAKICBmaWx0ZXIoY29tcGxhaW50X3R5cGUgPT0gIk5vaXNlIiB8IChjb21wbGFpbnRfdHlwZSA9PSAiQXR0YWNrIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzdWJ1cmIsIHkgPSBjb3VudCwgZmlsbCA9IGNvbXBsYWludF90eXBlKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKSArCiAgY29vcmRfZmxpcCgpIAoKYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgY29tcGxhaW50X3R5cGUpICU+JSAKICBmaWx0ZXIoY291bnQgPj0gNTAwKSAlPiUgCiAgZmlsdGVyKGNvbXBsYWludF90eXBlID09ICJOb2lzZSIgfCAoY29tcGxhaW50X3R5cGUgPT0gIkFnZ3Jlc3NpdmUgQW5pbWFsIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzdWJ1cmIsIHkgPSBjb3VudCwgZmlsbCA9IGNvbXBsYWludF90eXBlKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKSArCiAgY29vcmRfZmxpcCgpIAoKYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgY29tcGxhaW50X3R5cGUpICU+JSAKICBmaWx0ZXIoY291bnQgPj0gNTAwKSAlPiUgCiAgZmlsdGVyKGNvbXBsYWludF90eXBlID09ICJXYW5kZXJpbmciIHwgKGNvbXBsYWludF90eXBlID09ICJBZ2dyZXNzaXZlIEFuaW1hbCIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc3VidXJiLCB5ID0gY291bnQsIGZpbGwgPSBjb21wbGFpbnRfdHlwZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJmaWxsIikgKwogIGNvb3JkX2ZsaXAoKSAKCmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShzdWJ1cmIpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCksIGNvbXBsYWludF90eXBlKSAlPiUgCiAgZmlsdGVyKGNvdW50ID49IDUwMCkgJT4lIAogIGZpbHRlcihjb21wbGFpbnRfdHlwZSA9PSAiRW5jbG9zdXJlIiB8IChjb21wbGFpbnRfdHlwZSA9PSAiTm9pc2UiKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHN1YnVyYiwgeSA9IGNvdW50LCBmaWxsID0gY29tcGxhaW50X3R5cGUpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZmlsbCIpICsKICBjb29yZF9mbGlwKCkgCmBgYAoKRm9yIHRoZSBsZXNzIHRoYW4gNTAwIGdyZWF0ZXIgdGhhbiA1MCBncm91cHM6CmBgYHtyfQphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoc3VidXJiKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCBjb21wbGFpbnRfdHlwZSkgJT4lIAogIGZpbHRlcihjb3VudCA8IDUwMCAmIGNvdW50ID4gMTAwKSAlPiUgCiAgZmlsdGVyKGNvbXBsYWludF90eXBlID09ICJOb2lzZSIgfCAoY29tcGxhaW50X3R5cGUgPT0gIkF0dGFjayIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc3VidXJiLCB5ID0gY291bnQsIGZpbGwgPSBjb21wbGFpbnRfdHlwZSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJmaWxsIikgKwogIGNvb3JkX2ZsaXAoKSAKCmFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShzdWJ1cmIpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCksIGNvbXBsYWludF90eXBlKSAlPiUgCiAgZmlsdGVyKGNvdW50IDwgNTAwICYgY291bnQgPiAxMDApICU+JSAgCiAgZmlsdGVyKGNvbXBsYWludF90eXBlID09ICJOb2lzZSIgfCAoY29tcGxhaW50X3R5cGUgPT0gIkFnZ3Jlc3NpdmUgQW5pbWFsIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzdWJ1cmIsIHkgPSBjb3VudCwgZmlsbCA9IGNvbXBsYWludF90eXBlKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKSArCiAgY29vcmRfZmxpcCgpIAoKYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgY29tcGxhaW50X3R5cGUpICU+JSAKICBmaWx0ZXIoY291bnQgPCA1MDAgJiBjb3VudCA+IDEwMCkgJT4lIAogIGZpbHRlcihjb21wbGFpbnRfdHlwZSA9PSAiV2FuZGVyaW5nIiB8IChjb21wbGFpbnRfdHlwZSA9PSAiQWdncmVzc2l2ZSBBbmltYWwiKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHN1YnVyYiwgeSA9IGNvdW50LCBmaWxsID0gY29tcGxhaW50X3R5cGUpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZmlsbCIpICsKICBjb29yZF9mbGlwKCkgCgphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoc3VidXJiKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCBjb21wbGFpbnRfdHlwZSkgJT4lIAogIGZpbHRlcihjb3VudCA8IDUwMCAmIGNvdW50ID4gMTAwKSAlPiUgCiAgI2ZpbHRlcihjb21wbGFpbnRfdHlwZSA9PSAiRW5jbG9zdXJlIiB8IChjb21wbGFpbnRfdHlwZSA9PSAiTm9pc2UiKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHN1YnVyYiwgeSA9IGNvdW50LCBmaWxsID0gY29tcGxhaW50X3R5cGUpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZmlsbCIpICsKICBjb29yZF9mbGlwKCkgKwogIGZhY2V0X3dyYXAofiBzdWJ1cmIpCmBgYAoKCmBgYHtyfQphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoc3VidXJiKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCBjb21wbGFpbnRfdHlwZSwgYW5pbWFsX3R5cGUpICU+JSAKICBmaWx0ZXIoY291bnQgPCA1MDAgJiBjb3VudCA+IDEwMCkgJT4lIAogIGdncGxvdChhZXMoeCA9IGNvbXBsYWludF90eXBlLCB5ID0gY291bnQsIGZpbGwgPSBjb21wbGFpbnRfdHlwZSkpICsKICBnZW9tX2NvbCgpICsKICBmYWNldF93cmFwKH4gc3VidXJiKQpgYGAKCkZyb20gdGhpcyBncmFwaCwgd2UgY2FuIHNlZSB0aGF0IEh5ZGUgUGFyayBoYXMgYSBkaXNwcm9wb3J0aW9uYXRlIGFtb3VudCBvZiBwcml2YXRlIGltcG91bmRzLCB3aGlsZSBCb2hsZSBwbGFpbnMgaGFzIG1vcmUgbm9pc2UgY29tcGxhaW50cy4KClBvdGVudGlhbCBoeXBvdGhlc2lzIHRlc3Q6CgpUaGF0IHRoZSBsZXZlbCBvZiBwcml2YXRlIGltcG91bmRzIGluIEh5ZGUgUGFyayBiZWluZyBncmVhdGVyIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuCgpUaGF0IHRoZSBsZXZlbCBvZiBub2lzZSBpbiBCb2hsZSBQbGFpbnMgYmVpbmcgZ3JlYXRlciBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LgpgYGB7cn0KYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KHN1YnVyYikgJT4lIAogIGNvdW50KCkgJT4lIAogIGZpbHRlcihuIDwgNTAwICYgbiA+IDEwMCkKYGBgCgoKCgoKCkxldCdzIGxvb2sgYXQgdGhlIHN1YnVyYnMgd2l0aCBtdWNoIGhpZ2hlciBjb21wbGFpbnRzIG5vdzoKCmBgYHtyfQphbmltYWxfY29tcGxhaW50cyAlPiUgCiAgZ3JvdXBfYnkoc3VidXJiKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCBjb21wbGFpbnRfdHlwZSwgYW5pbWFsX3R5cGUpICU+JSAKICBmaWx0ZXIoY291bnQgPj0gNTAwICYgY291bnQgPDQwMDApICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBjb21wbGFpbnRfdHlwZSwgeSA9IGNvdW50LCBmaWxsID0gY29tcGxhaW50X3R5cGUpKSArCiAgZ2VvbV9jb2woKSArCiAgZmFjZXRfd3JhcCh+IHN1YnVyYikKYGBgCgoKCgoKIyMjIDIuIGEpIEFyZSB0aGVyZSBhbnkgbWFqb3IgZGlmZmVyZW5jZXMgYmV0d2VlbiByZWdpb25zPwoKYikgSG93IGRvIHRoZSBhbmltYWwgb3V0Y29tZXMgZGlmZmVyIG92ZXIgdGltZT8KCmMpIEFyZSB0aGVyZSBhbnkgbm90aWNlYWJsZSBhbm9tYWxpZXMgaW4gdGhlIGRhdGE/CgoKSXQncyBpbXBvc3NpYmxlIHRvIHNheSBpZiB0aGVyZSdzIGRpZmZlcmVudCBwZWFrcyBvZiB0aW1lcyBvZiB5ZXIgcGVyIHJlZ2lvbiwgYXMgd2Ugb25seSBoYXZlIHRoZSBkYXRhIGZvciB0aGUgeWVhciBhcyBhIHdob2xlLiBVbmxlc3Mgd2UgbG9vayBhdCBTdWJ1cmIgcmF0aGVyIHRoYW4gcmVnaW9uLCBhbmQgYnJlYWsgdGhpcyBkb3duIGJ5IHRpbWUuIEhvd2V2ZXIsIEkgdGhpbmsgaXQnZCBiZSBnb29kIHRvIHVzZSB0aGUgZ2VuZXJhbCBBdXRyYWxpYSAobmF0aW9ud2lkZSkgZGF0YS4KCgpQcm9wb3J0aW9ucyBvdmVyYWxsIGJ5IHJlZ2lvbiBhbmQgYnkgb3V0Y29tZS4gV2UgY2FuIHNlZSB0aGF0IGluIGdlbmVyYWwsIHJlZ2lvbnMgaGF2ZSBwcmV0dHkgc2ltaWxhciBwcm9wb3J0aW9ucyBhY3Jvc3MgYWxsIG91dGNvbWVzLiBUaGlzIHdvbid0IGJlIHRoZSBjYXNlIGZvciBldmVyeSB5ZWFyIHRob3VnaCBhbmQgdHJlbmRzIG92ZXIgdGltZSwgdGhhdCdzIHRoZSBtb3JlIGludGVyZXN0aW5nIHN0dWZmLgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIGV2YWw9VFJVRX0KYW5pbWFsX291dGNvbWVzICU+JSAKICBnZ3Bsb3QoYWVzKHggPSByZWdpb24sIHkgPSBudW1iZXJfb2Zfb2NjdXJlbmNlcywgZmlsbCA9IG91dGNvbWUsIGNvbCA9IG91dGNvbWUpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZmlsbCIpCmBgYAoKVGhpcyBpcyB0aGUgc2FtZSB0aGluZyBhcyBiZWZvcmUsIGJ1dCBmb3IgYW5pbWFsIHR5cGUuIFNhbWUgYXMgYmVmb3JlLCBub3QgbXVjaCBkaXNjZXJuaWJsZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHJlZ2lvbnMuCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgZXZhbD1UUlVFfQphbmltYWxfb3V0Y29tZXMgJT4lIAogIGdncGxvdChhZXMoeCA9IHJlZ2lvbiwgeSA9IG51bWJlcl9vZl9vY2N1cmVuY2VzLCBmaWxsID0gYW5pbWFsX3R5cGUsIGNvbCA9IGFuaW1hbF90eXBlKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKQpgYGAKCgoKCk5leHQgaXMganVzdCB0aGUgc3VtIG9jdXJyZW5jZXMuIFdlIGNhbiBzZWUgdGhlIHJlZ2lvbnMgdGhhdCBoYXZlIHdheSBtb3JlIGFuaW1hbHMgaW5qdXJlZC90YWtlbiBpbiBieSB0aGUgUlNQQ0EuIFRoaXMgY291bGQgYmUgYSBwb3B1bGF0aW9uIHRoaW5nLCBtYXliZSB0aGVzZSByZWdpb25zIGp1c3QgaGF2ZSBtb3JlIHdpbGRsaWZlIHBvcHVsYXRpb25zIGV0Yy4sIG9yIGV2ZW4gYSBiaWdnZXIgUlNQQ0EgcHJlc2VuY2UgbGVhZGluZyB0byBtb3JlIGNhc2VzLgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIGV2YWw9VFJVRX0KYW5pbWFsX291dGNvbWVzICU+JSAKICBncm91cF9ieShyZWdpb24pICU+JSAKICBzdW1tYXJpc2Uoc3VtX29mX29jY3VyZW5jZXMgPSBzdW0obnVtYmVyX29mX29jY3VyZW5jZXMsIG5hLnJtID0gVFJVRSkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSByZWdpb24sIHkgPSBzdW1fb2Zfb2NjdXJlbmNlcykpICsKICBnZW9tX2NvbChjb2wgPSAiYmx1ZSIsIGZpbGwgPSAiYmx1ZSIpCmBgYAoKCgpTbywgdGhpcyBpcyB0aGUgZGF0YSBhY3Jvc3MgdGltZSAoZnJvbSAxOTk5LTIwMTgpLCB3aXRoIHRpbWUgb24gdGhlIHgtYXhpcyBhbmQgbnVtYmVyIG9mIG9jY3VyZW5jZXMgb24gdGhlIHkuIEZhY2V0ZWQgaW50byBncmFwaHMgYmFzZWQgb24gb3V0Y29tZSwgd2l0aCB0aGUgY29sb3VyZWQgbGluZXMgcmVwcmVzZW50aW5nIGRpZmZlcmVudCByZWdpb25zLgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIGV2YWw9VFJVRX0KYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGdyb3VwX2J5KHJlZ2lvbiwgb3V0Y29tZSwgeWVhcikgJT4lCiAgc3VtbWFyaXplKHRvdGFsX2luanVyaWVzID0gc3VtKG51bWJlcl9vZl9vY2N1cmVuY2VzKSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdG90YWxfaW5qdXJpZXMsIGNvbG9yID0gcmVnaW9uKSkgKwogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKH5vdXRjb21lLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJOdW1iZXIgb2YgaW5qdXJpZXMiLCBjb2xvciA9ICJSZWdpb24iKQoKYGBgCgpXaGF0IGNhbiB3ZSBzYXkgYWJvdXQgdGhpcz8gV2VsbCwgUUxEIGhhcyBoYWQgdGhlaXIgdHJhbnNmZXJzIGdvIHdheSB1cCBzaW5jZSBhYm91dCAyMDA5LCBhbmQgaW4gZ2VuZXJhbCBsb29rcyBsaWtlIGFuIGluY3JlYXNlIGluIGNhc2VzIGZvciB0aGVtLiBOU1cgaGFkIGEgYmlnIHNwaWtlIG9mIEN1cnJlbnRseSBJbiBDYXJlIGFyb3VuZCAyMDA0LiBFdXRoYW5pc2F0aW9uIGluIGdlbmVyYWwgc2VlbXMgdG8gYmUgZmFsbGluZyBvdXQgb2YgZmF2b3VyICh3aGljaCBpcyBhY3R1YWxseSB0cnVlLCB0aGUgUlNQQ0EgdHJpZXMgdG8gZG8gaXQgbGVzcyBmb3IgdmFyaW91cyByZWFzb25zLCBvbmUgYWN0dWFsbHkgYmVpbmcgdGhlIG1lbnRhbCBoZWFsdGggb2YgdGhlIHN0YWZmIGFuZCBhbm90aGVyIGJlaW5nIGxvdHMgb2YgZXV0aGFuaXNhdGlvbnMgbGVhZHMgdG8gYSBuZWdhdGl2ZSBwZXJjZXB0aW9uIG9mIGFuaW1hbCBzaGVsdGVycykKCgoKCkV4YWN0IHNhbWUgYXMgYmVmb3JlLCBidXQgZmFjZXRlZCBvbiBhbmltYWwgdHlwZSByYXRoZXIgdGhhbiBvdXRjb21lLgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIGV2YWw9VFJVRX0KYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGdyb3VwX2J5KHJlZ2lvbiwgYW5pbWFsX3R5cGUsIHllYXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9pbmp1cmllcyA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX2luanVyaWVzLCBjb2xvciA9IHJlZ2lvbikpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+YW5pbWFsX3R5cGUsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIk51bWJlciBvZiBpbmp1cmllcyIsIGNvbG9yID0gIlJlZ2lvbiIpCmBgYAoKUUxEIGhhcyBoYWQgYSBsb3QgbW9yZSB3aWxkbGlmZSBjYXNlcywgc3RlYWRpbHkgY2xpbWJpbmcgc2luY2UgYWJvdXQgMjAwNi4gTlNXIGhhcyBoYWQgYSBiaWcgZHJvcCBpbiBjYXRzIHJlY2VudGx5LiBEb2dzIHRvby4gSG9yc2VzIGhhdmUgZ29uZSB1cCBldmVyeSByZWdpb24gaXQgbG9va3MgbGlrZS4gTlQgaGFzIGhhZCBhIGh1Z2Ugc3Bpa2UgaW4gY2F0cyBmcm9tIDIwMTUtMjAxNi4KCgoKCgpUaGlzIG9uZSBoYXMgdGhlIHNhbWUgeCBhbmQgeSwgYnV0IGlzIGZhY2V0ZWQgYmFzZWQgb24gcmVnaW9uLiBUaGUgY29sb3VyZWQgbGluZXMgbm93IHJlcHJlc2VudCB0aGUgb3V0Y29tZXMuCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgZXZhbD1UUlVFfQphbmltYWxfb3V0Y29tZXMgJT4lIAogIGRyb3BfbmEoKSAlPiUgCiAgZ3JvdXBfYnkocmVnaW9uLCBvdXRjb21lLCB5ZWFyKSAlPiUKICBzdW1tYXJpemUodG90YWxfaW5qdXJpZXMgPSBzdW0obnVtYmVyX29mX29jY3VyZW5jZXMpKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB0b3RhbF9pbmp1cmllcywgY29sb3IgPSBvdXRjb21lKSkgKwogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKH5yZWdpb24sIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIk51bWJlciBvZiBpbmp1cmllcyIsIGNvbG9yID0gIk91dGNvbWUiKQpgYGAKCldBIGluIDIwMDYgaGFkIGEgYmlnIGluY3JlYXNlIGluIGV1dGhhbml6YXRpb25zLiBWSUMgaGFzIGhhZCB0aGVpcnMgc3RlYWRpbHkgZGVjcmVhc2luZyBvdmVyIHRpbWUsIHRoaXMgaXMgcmVmbGVjdGVkIGFsc28gaW4gTlNXLCBUQVMgYW5kIEFDVC4KCgoKCgpTYW1lIGFzIGJlZm9yZSB3aXRoIGZhY2V0aW5nIGJhc2VkIG9uIHJlZ2lvbiwgYnV0IG5vdyB0aGUgY29sb3VyZWQgbGluZXMgcmVwcmVzZW50IHRoZSB0eXBlIG9mIGFuaW1hbCB0aGUgUlNQQ0EgaXMgZGVhbGluZyB3aXRoLgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIGV2YWw9VFJVRX0KYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGdyb3VwX2J5KHJlZ2lvbiwgYW5pbWFsX3R5cGUsIHllYXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9pbmp1cmllcyA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX2luanVyaWVzLCBjb2xvciA9IGFuaW1hbF90eXBlKSkgKwogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKH5yZWdpb24sIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIk51bWJlciBvZiBpbmp1cmllcyIsIGNvbG9yID0gIkFuaW1hbCBUeXBlIikKYGBgCgpOVCBoYXMgaGFkIGEgYmlnIHNwaWtlIGluIGRvZ3MgYW5kIGNhdHMgaW4gcmVjZW50IHllYXJzLiBXQSBoYWQgYSBiaWcgc3Bpa2UgaW4gd2lsZGxpZmUgaW4gMjAwNSwgY29ycmVzcG9uZGluZyB3aXRoIHRoZWlyIHNwaWtlIGluIGV1dGhhbml6YXRpb25zIC0gY29tbW9uIHNlbnNlIGFuZCBkb21haW4ga25vd2xlZGdlIHRlbGwgdXMgdGhlc2UgYXJlIGxpa2VseSBoaWdobHkgY29ycmVsYXRlZC4gVklDJ3MgbnVtYmVycyBpbiBnZW5lcmFsIHNlZW0gdG8gYmUgZGVjcmVhc2luZyBvdmVyIHRpbWUuCgoKCgpMb29raW5nIG5vdyBzcGVjaWZpY2FsbHkgYXQgZXV0aGFuaXphdGlvbnMsIGZhY2V0ZWQgYnkgcmVnaW9uIHdpdGggdGhlIGxpbmVzIHJlcHJlc2VudGluZyBldXRoYW5pemF0aW9ucy4KYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBldmFsPVRSVUV9CmFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZHJvcF9uYSgpICU+JSAKICBncm91cF9ieShyZWdpb24sIG91dGNvbWUsIHllYXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9pbmp1cmllcyA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKG91dGNvbWUgPT0gIkV1dGhhbml6ZWQiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX2luanVyaWVzLCBjb2xvciA9IG91dGNvbWUpKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbiwgc2NhbGVzID0gImZyZWVfeSIpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSAiTnVtYmVyIG9mIGluanVyaWVzIiwgY29sb3IgPSAiT3V0Y29tZSIpCmBgYAoKCgpOb3cgd2Ugbm8gbG9uZ2VyIGZhY2V0IGJ5IHJlZ2lvbi4KYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBldmFsPVRSVUV9CmFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZHJvcF9uYSgpICU+JSAKICBncm91cF9ieShvdXRjb21lLCBhbmltYWxfdHlwZSwgeWVhcikgJT4lCiAgc3VtbWFyaXplKHRvdGFsX2luanVyaWVzID0gc3VtKG51bWJlcl9vZl9vY2N1cmVuY2VzKSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdG90YWxfaW5qdXJpZXMsIGNvbG9yID0gYW5pbWFsX3R5cGUpKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofm91dGNvbWUsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIk51bWJlciBvZiBpbmp1cmllcyIsIGNvbG9yID0gIkFuaW1hbCBUeXBlIikKCmFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZHJvcF9uYSgpICU+JSAKICBncm91cF9ieShvdXRjb21lLCBhbmltYWxfdHlwZSwgeWVhcikgJT4lCiAgc3VtbWFyaXplKHRvdGFsX2luanVyaWVzID0gc3VtKG51bWJlcl9vZl9vY2N1cmVuY2VzKSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdG90YWxfaW5qdXJpZXMsIGNvbG9yID0gb3V0Y29tZSkpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+YW5pbWFsX3R5cGUsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIk51bWJlciBvZiBpbmp1cmllcyIsIGNvbG9yID0gIk91dGNvbWUiKQpgYGAKCgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIGV2YWw9VFJVRX0KIyBsb29raW5nIGF0IG9ubHkgZXV0aGFuYXNpYQphbmltYWxfb3V0Y29tZXMgJT4lIAogIGRyb3BfbmEoKSAlPiUgCiAgZ3JvdXBfYnkob3V0Y29tZSwgYW5pbWFsX3R5cGUsIHllYXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9pbmp1cmllcyA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKG91dGNvbWUgPT0gIkV1dGhhbml6ZWQiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX2luanVyaWVzLCBjb2xvciA9IG91dGNvbWUpKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofmFuaW1hbF90eXBlLCBzY2FsZXMgPSAiZnJlZV95IikgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJOdW1iZXIgb2YgaW5qdXJpZXMiLCBjb2xvciA9ICJPdXRjb21lIikKCiMgbG9va2luZyBhdCBvbmx5IHJlaG9tZWQKYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGdyb3VwX2J5KG91dGNvbWUsIGFuaW1hbF90eXBlLCB5ZWFyKSAlPiUKICBzdW1tYXJpemUodG90YWxfaW5qdXJpZXMgPSBzdW0obnVtYmVyX29mX29jY3VyZW5jZXMpKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcihvdXRjb21lID09ICJSZWhvbWVkIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB0b3RhbF9pbmp1cmllcywgY29sb3IgPSBvdXRjb21lKSkgKwogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKH5hbmltYWxfdHlwZSwgc2NhbGVzID0gImZyZWVfeSIpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSAiTnVtYmVyIG9mIGluanVyaWVzIiwgY29sb3IgPSAiT3V0Y29tZSIpCmBgYAoKT0sgc28gY2F0cyBhbmQgZG9ncyBoYXZlIHdheSBsZXNzIGV1dGhhbmlzYXRpb25zLiBXaWxkbGlmZSBoYXMgZ29uZSB3YXkgdXAhIEhvcnNlcyBhcmUgdG9vIHNtYWxsIGEgc2FtcGxlIHRvIGJlIG1lYW5pbmdmdWwuIE90aGVyIGFuaW1hbHMgaGF2ZSBzcGlrZWQgdGhlbiBkZWNyZWFzZWQuCgoKCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgZXZhbD1UUlVFfQojIGxvb2tpbmcgYXQgYm90aCByZWhvbWVkIGFuZCBldXRoYW5pemVkCmFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZHJvcF9uYSgpICU+JSAKICBncm91cF9ieShvdXRjb21lLCBhbmltYWxfdHlwZSwgeWVhcikgJT4lCiAgc3VtbWFyaXplKHRvdGFsX2luanVyaWVzID0gc3VtKG51bWJlcl9vZl9vY2N1cmVuY2VzKSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBmaWx0ZXIob3V0Y29tZSA9PSAiUmVob21lZCIgfCBvdXRjb21lID09ICJFdXRoYW5pemVkIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB0b3RhbF9pbmp1cmllcywgY29sb3IgPSBvdXRjb21lKSkgKwogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKH5hbmltYWxfdHlwZSwgc2NhbGVzID0gImZyZWVfeSIpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSAiTnVtYmVyIG9mIGluanVyaWVzIiwgY29sb3IgPSAiT3V0Y29tZSIpCmBgYAoKTG9va2luZyBhdCByZWhvbWVzIHRvIGV1dGhhbmlzYXRpb25zLCB3ZSBzZWUgY2F0cyBoYXZlIGFuIHVwd2FyZCB0cmVuZCB3aXRoIGxlc3MgZXV0aGFuaXNhdGlvbnMgYW5kIG1vcmUgcmVob21lcywgd2l0aCBkb2dzLCBib3RoIGhhdmUgZ29uZSBkb3duLiBQZXJoYXBzIHdpdGggZG9ncyB0aGVyZSdzIGEgY29uZm91bmRpbmcgZmFjdG9yLiBJbiBmYWN0LCBpdCBzZWVtcyBsaWtlIHRoZSBSU1BDQSBpcyBkZWFsaW5nIHdpdGggbGVzcyBkb2dzIGluIGdlbmVyYWwuCgoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCBldmFsPVRSVUV9CiMgbG9va2luZyBhdCBib3RoIHJlaG9tZWQsIHJlY2xhaW1lZCBhbmQgZXV0aGFuaXplZAphbmltYWxfb3V0Y29tZXMgJT4lIAogIGRyb3BfbmEoKSAlPiUgCiAgZ3JvdXBfYnkob3V0Y29tZSwgYW5pbWFsX3R5cGUsIHllYXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9pbmp1cmllcyA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKG91dGNvbWUgPT0gIlJlaG9tZWQiIHwgb3V0Y29tZSA9PSAiRXV0aGFuaXplZCIgfCBvdXRjb21lID09ICJSZWNsYWltZWQiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdG90YWxfaW5qdXJpZXMsIGNvbG9yID0gb3V0Y29tZSkpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfd3JhcCh+YW5pbWFsX3R5cGUsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIk51bWJlciBvZiBpbmp1cmllcyIsIGNvbG9yID0gIk91dGNvbWUiKQpgYGAKCgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIGV2YWw9VFJVRX0KYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGdyb3VwX2J5KG91dGNvbWUsIGFuaW1hbF90eXBlLCB5ZWFyKSAlPiUKICBzdW1tYXJpemUodG90YWxfaW5qdXJpZXMgPSBzdW0obnVtYmVyX29mX29jY3VyZW5jZXMpKSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGZpbHRlcihhbmltYWxfdHlwZSA9PSAiV2lsZGxpZmUiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX2luanVyaWVzLCBjb2xvciA9IG91dGNvbWUpKSArCiAgZ2VvbV9saW5lKCkgKwogIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJOdW1iZXIgb2YgaW5qdXJpZXMiLCBjb2xvciA9ICJPdXRjb21lIiwgdGl0bGUgPSAiV2lsZGxpZmUiKQoKYW5pbWFsX291dGNvbWVzICU+JSAKICBkcm9wX25hKCkgJT4lIAogIGdyb3VwX2J5KG91dGNvbWUsIGFuaW1hbF90eXBlLCB5ZWFyLCByZWdpb24pICU+JQogIHN1bW1hcml6ZSh0b3RhbF9pbmp1cmllcyA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKGFuaW1hbF90eXBlID09ICJXaWxkbGlmZSIgJiBvdXRjb21lID09ICJFdXRoYW5pemVkIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB0b3RhbF9pbmp1cmllcywgY29sb3IgPSBvdXRjb21lKSkgKwogIGdlb21fbGluZSgpICsKICBmYWNldF93cmFwKH5yZWdpb24sIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIk51bWJlciBvZiBpbmp1cmllcyIsIGNvbG9yID0gIk91dGNvbWUiLCB0aXRsZSA9ICJXaWxkbGlmZSIpCmBgYAoKRXV0aGFuaXphdGlvbnMgZm9yIHdpbGRsaWZlIGhhdmUgb3ZlcmFsbCBnb25lIHVwLiBRdWVlbnNsYW5kIGlzIHNrZXdpbmcgdGhlIGRhdGEsIHRoZXkndmUgZXV0aGFuaXplZCB3YXkgbW9yZSEgSXMgdGhpcyBuZWNlc3NhcmlseSBhIGJhZCB0aGluZz8gSXQgY291bGQgaW5kaWNhdGUgYSBiaWdnZXIgUlNQQ0EgcHJlc2VuY2UgaW4gdGhlIGFyZWEsIGFuZCBtb3JlIHZpZ2lsYW5jZSBpbiByZWdhcmRzIHRvIGNvbnRyb2xsaW5nIHRoZSB3aWxkbGlmZS4gCgoKCgpHZW5lcmFsIHRob3VnaHRzOgoKYmlnIGNoYW5nZSBpbiAyMDA2IGZvciBXQTsgY3ljbG9uZSBFbW1hIE1hcmNoIDIwMDYgY291bGQndmUgcmVsZWFzZWQgbWFueSB3aWxkIGFuaW1hbHMgbGVhZGluZyB0byBoaWdoIGV1dGhhbml6YXRpb25zICh0aGlzIGZvciAyLmMpCmRpZmZlcmVudCB0ZXJyaXRvcmllcyBoYXZlIGRpZmZlcmVudCBhcHByb2FjaGVzOyAKCgoKIyMjIDQuIEJ1c2luZXNzIEludGVsbGlnZW5jZSDigJMgdXNpbmcgdGhlIGluc2lnaHRzIHlvdSBoYXZlIGZvdW5kLCBjYW4geW91IHByZWRpY3QgaG93IHRoaXMgbWlnaHQgbG9vayBmb3IgdGhlIHVwY29taW5nIHllYXI/CgoKYGBge3J9CiMgTG9hZCByZXF1aXJlZCBwYWNrYWdlcwpsaWJyYXJ5KGZvcmVjYXN0KQoKIyBDcmVhdGUgYSB0aW1lIHNlcmllcyBvYmplY3QKdHNfZGF0YSA8LSB0cyhhbmltYWxfb3V0Y29tZXMkb3V0Y29tZSwgc3RhcnQgPSBjKDE5OTkpLCBmcmVxdWVuY3kgPSAxKQoKIyBGaXQgYW4gQVJJTUEgbW9kZWwKYXJpbWFfbW9kZWwgPC0gYXV0by5hcmltYSh0c19kYXRhKQoKIyBNYWtlIGZvcmVjYXN0cyBmb3IgdGhlIG5leHQgNSB5ZWFycwpmb3JlY2FzdF92YWx1ZXMgPC0gZm9yZWNhc3QoYXJpbWFfbW9kZWwsIGggPSA1KQoKIyBQbG90IHRoZSBmb3JlY2FzdHMKYXV0b3Bsb3QoZm9yZWNhc3RfdmFsdWVzKQoKYGBgCgoKYGBge3J9CmFuaW1hbF9vdXRjb21lcyAlPiUgCiAgZHJvcF9uYSgpICU+JSAKICBncm91cF9ieShyZWdpb24sIG91dGNvbWUsIHllYXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9pbmp1cmllcyA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKG91dGNvbWUgPT0gIkV1dGhhbml6ZWQiKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX2luanVyaWVzLCBjb2xvciA9IG91dGNvbWUpKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbiwgc2NhbGVzID0gImZyZWVfeSIpICsKICBsYWJzKHggPSAiRGF0ZSIsIHkgPSAiTnVtYmVyIG9mIGluanVyaWVzIiwgY29sb3IgPSAiT3V0Y29tZSIpCmBgYAoKCmBgYHtyfQojIExvYWQgcmVxdWlyZWQgcGFja2FnZXMKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQoKIyBDcmVhdGUgYSBuZXcgZGF0YSBmcmFtZSB3aXRoIGdyb3VwZWQgYW5kIHN1bW1hcml6ZWQgZGF0YQpncm91cGVkX2RhdGEgPC0gYW5pbWFsX291dGNvbWVzICU+JQogIGRyb3BfbmEoKSAlPiUKICBncm91cF9ieShyZWdpb24sIG91dGNvbWUsIHllYXIpICU+JQogIHN1bW1hcml6ZSh0b3RhbF9vY2N1cnJlbmNlcyA9IHN1bShudW1iZXJfb2Zfb2NjdXJlbmNlcykpCgojIEZpbHRlciB0aGUgZGF0YSB0byBvbmx5IGluY2x1ZGUgZXV0aGFuaXplZCBvdXRjb21lcwpldXRoYW5pemVkX2RhdGEgPC0gZ3JvdXBlZF9kYXRhICU+JQogIGZpbHRlcihvdXRjb21lID09ICJFdXRoYW5pemVkIikKCiMgQ3JlYXRlIGEgbGluZSBwbG90IG9mIHRvdGFsIGV1dGhhbml6ZWQgb2NjdXJyZW5jZXMgYnkgeWVhciBhbmQgcmVnaW9uCmdncGxvdChldXRoYW5pemVkX2RhdGEsIGFlcyh4ID0geWVhciwgeSA9IHRvdGFsX29jY3VycmVuY2VzLCBjb2xvciA9IHJlZ2lvbikpICsKICBnZW9tX2xpbmUoKSArCiAgbGFicyh4ID0gIlllYXIiLCB5ID0gIlRvdGFsIEV1dGhhbml6ZWQgT2NjdXJyZW5jZXMiLCBjb2xvciA9ICJSZWdpb24iKSArCiAgZmFjZXRfd3JhcCh+cmVnaW9uLCBzY2FsZXMgPSAiZnJlZV95IikKCmBgYAoKYGBge3J9CiMgTG9hZCByZXF1aXJlZCBwYWNrYWdlcwpsaWJyYXJ5KGZvcmVjYXN0KQoKIyBDb252ZXJ0IHRoZSBkYXRhIHRvIGEgdGltZSBzZXJpZXMgb2JqZWN0CnRzX2RhdGEgPC0gdHMoZXV0aGFuaXplZF9kYXRhJHRvdGFsX29jY3VycmVuY2VzLCBzdGFydCA9IGMoMTk5OSwgMSksIGZyZXF1ZW5jeSA9IDEpCgojIEZpdCBhbiBBUklNQSBtb2RlbCB0byB0aGUgdGltZSBzZXJpZXMgZGF0YQphcmltYV9tb2RlbCA8LSBhdXRvLmFyaW1hKHRzX2RhdGEpCgojIE1ha2UgZm9yZWNhc3RzIGZvciB0aGUgbmV4dCA1IHllYXJzCmZvcmVjYXN0X3ZhbHVlcyA8LSBmb3JlY2FzdChhcmltYV9tb2RlbCwgaCA9IDUpCgojIFBsb3QgdGhlIGZvcmVjYXN0ZWQgdmFsdWVzIGFuZCB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCnBsb3QoZm9yZWNhc3RfdmFsdWVzLCB4bGFiID0gIlllYXIiLCB5bGFiID0gIlRvdGFsIEV1dGhhbml6ZWQgT2NjdXJyZW5jZXMiLCBtYWluID0gIkFSSU1BIEZvcmVjYXN0IiwgeGxpbSA9IGMoMTk5OSwgMjAyMykpCgpgYGAKCgojIyMgQ3JlYXRpbmcgYSBtb2RlbCBmb3IgVG93bnN2aWxsZSBUb3RhbCBjYXNlczoKCmBgYHtyfQpsaWJyYXJ5KGdndGhlbWVzKQoKYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KGRhdGVfcmVjZWl2ZWQpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JSAKICBnZ3Bsb3QoKSArCiAgYWVzKHggPSBkYXRlX3JlY2VpdmVkLCB5ID0gY291bnQgKSArCiAgZ2VvbV9saW5lKGNvbCA9ICJibHVlIikgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICI2IG1vbnRocyIsIGRhdGVfbGFiZWxzID0gIiViICV5IikgKyAKICBsYWJzKHRpdGxlID0gIlRvd25zdmlsbGUgQ29tcGxhaW50IENhbGxzIiwKICAgICAgIHggPSAiVGltZSIsCiAgICAgICB5ID0gIk51bWJlciBvZiBDYWxscyIpICsKICB0aGVtZV9lY29ub21pc3QoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgdmp1c3QgPSAxLCBmYW1pbHkgPSAibW9ubyIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSA3KSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQodmp1c3QgPSAzLjIpLAogICAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJtb25vIiwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNCkpICsKICAgICAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBhcy5EYXRlKCIyMDE0LTA2LTAxIiksIHhtYXggPSBhcy5EYXRlKCIyMDE0LTA4LTAxIiksIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCBmaWxsID0gImdyYXk3MCIsIGFscGhhID0gMC4zKSArCiAgICAgICAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gYXMuRGF0ZSgiMjAxNS0wNi0wMSIpLCB4bWF4ID0gYXMuRGF0ZSgiMjAxNS0wOC0wMSIpLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZmlsbCA9ICJncmF5NzAiLCBhbHBoYSA9IDAuMykgKwogICAgICAgIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IGFzLkRhdGUoIjIwMTYtMDYtMDEiKSwgeG1heCA9IGFzLkRhdGUoIjIwMTYtMDgtMDEiKSwgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsIGZpbGwgPSAiZ3JheTcwIiwgYWxwaGEgPSAwLjMpICsKICAgICAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBhcy5EYXRlKCIyMDE3LTA2LTAxIiksIHhtYXggPSBhcy5EYXRlKCIyMDE3LTA4LTAxIiksIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCBmaWxsID0gImdyYXk3MCIsIGFscGhhID0gMC4zKSArCiAgICAgICAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gYXMuRGF0ZSgiMjAxOC0wNi0wMSIpLCB4bWF4ID0gYXMuRGF0ZSgiMjAxOC0wOC0wMSIpLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZmlsbCA9ICJncmF5NzAiLCBhbHBoYSA9IDAuMykgKwogICAgICAgIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IGFzLkRhdGUoIjIwMTktMDYtMDEiKSwgeG1heCA9IGFzLkRhdGUoIjIwMTktMDgtMDEiKSwgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsIGZpbGwgPSAiZ3JheTcwIiwgYWxwaGEgPSAwLjMpCmBgYAoKdGhpcyBzb3J0YSB3b3JrczoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGZvcmVjYXN0KQpsaWJyYXJ5KGdndGhlbWVzKQoKCiMgQ3JlYXRlIGEgdGltZSBzZXJpZXMgZnJvbSB0aGUgZGF0YQphbmltYWxfY29tcGxhaW50c190cyA8LSBhbmltYWxfY29tcGxhaW50cyAlPiUKICBncm91cF9ieShkYXRlX3JlY2VpdmVkKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JQogIHRzKGZyZXF1ZW5jeSA9IDM2NSkKCiMgRm9yZWNhc3RpbmcgZm9yIG5leHQgMyB5ZWFycwphbmltYWxfY29tcGxhaW50c19mYyA8LSBmb3JlY2FzdChhbmltYWxfY29tcGxhaW50c190cywgaCA9IDMqMzY1KQoKIyBQbG90IHRoZSBvcmlnaW5hbCBkYXRhIGFuZCBmb3JlY2FzdAphdXRvcGxvdChhbmltYWxfY29tcGxhaW50c19mYywgCiAgICAgICAgIG1haW4gPSAiVG93bnN2aWxsZSBDb21wbGFpbnQgQ2FsbHMgRm9yZWNhc3QiLCAKICAgICAgICAgeGxhYiA9ICJUaW1lIiwKICAgICAgICAgeWxhYiA9ICJOdW1iZXIgb2YgQ2FsbHMiKSArIAogIGF1dG9sYXllcihhbmltYWxfY29tcGxhaW50c190cywgCiAgICAgICAgICAgIHNlcmllcyA9ICJPcmlnaW5hbCBEYXRhIiwKICAgICAgICAgICAgY29sID0gImJsdWUiKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfYnJlYWtzID0gIjYgbW9udGhzIiwgZGF0ZV9sYWJlbHMgPSAiJWIgJXkiKSArCiAgdGhlbWVfZWNvbm9taXN0KCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIHZqdXN0ID0gMSwgZmFtaWx5ID0gIm1vbm8iLCBmYWNlID0gImJvbGQiLCBzaXplID0gNyksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHZqdXN0ID0gMy4yKSwKICAgICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAibW9ubyIsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjQpKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gYXMuRGF0ZSgiMjAxNC0wNi0wMSIpLCB4bWF4ID0gYXMuRGF0ZSgiMjAxNC0wOC0wMSIpLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZmlsbCA9ICJncmF5NzAiLCBhbHBoYSA9IDAuMykgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IGFzLkRhdGUoIjIwMTUtMDYtMDEiKSwgeG1heCA9IGFzLkRhdGUoIjIwMTUtMDgtMDEiKSwgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsIGZpbGwgPSAiZ3JheTcwIiwgYWxwaGEgPSAwLjMpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBhcy5EYXRlKCIyMDE2LTA2LTAxIiksIHhtYXggPSBhcy5EYXRlKCIyMDE2LTA4LTAxIiksIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCBmaWxsID0gImdyYXk3MCIsIGFscGhhID0gMC4zKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gYXMuRGF0ZSgiMjAxNy0wNi0wMSIpLCB4bWF4ID0gYXMuRGF0ZSgiMjAxNy0wOC0wMSIpLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZmlsbCA9ICJncmF5NzAiLCBhbHBoYSA9IDAuMykgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IGFzLkRhdGUoIjIwMTgtMDYtMDEiKSwgeG1heCA9IGFzLkRhdGUoIjIwMTgtMDgtMDEiKSwgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsIGZpbGwgPSAiZ3JheTcwIiwgYWxwaGEgPSAwLjMpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBhcy5EYXRlKCIyMDE5LTA2LTAxIiksIHhtYXggPSBhcy5EYXRlKCIyMDE5LTA4LTAxIiksIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCBmaWxsID0gImdyYXk3MCIsIGFscGhhID0gMC4zKQoKYGBgCgpgYGB7cn0KbGlicmFyeShmb3JlY2FzdCkKbGlicmFyeShnZ3RoZW1lcykKCiMgQ29udmVydCB0aGUgZGF0ZV9yZWNlaXZlZCBjb2x1bW4gdG8gYSBEYXRlIHR5cGUKCiMgQWdncmVnYXRlIHRoZSBkYXRhIHRvIGdldCB0aGUgY291bnQgb2YgY29tcGxhaW50cyBwZXIgZGF5CmFuaW1hbF9jb21wbGFpbnRzIDwtIGFuaW1hbF9jb21wbGFpbnRzICU+JSAKICBncm91cF9ieShkYXRlX3JlY2VpdmVkKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUgCiAgdW5ncm91cCgpCgojIENvbnZlcnQgdGhlIGRhdGEgdG8gYSB0aW1lIHNlcmllcyBvYmplY3QKdHNfZGF0YSA8LSB0cyhhbmltYWxfY29tcGxhaW50cyRjb3VudCwgZnJlcXVlbmN5ID0gMzY1KQoKIyBEZWNvbXBvc2UgdGhlIHRpbWUgc2VyaWVzIHVzaW5nIFNUTAp0c19zdGwgPC0gc3RsKHRzX2RhdGEsIHMud2luZG93ID0gInBlcmlvZGljIikKCiMgUGxvdCB0aGUgb3JpZ2luYWwgdGltZSBzZXJpZXMgYW5kIGl0cyBjb21wb25lbnRzCmF1dG9wbG90KHRzX3N0bCkgKwogIGxhYnModGl0bGUgPSAiU1RMIERlY29tcG9zaXRpb24gb2YgQW5pbWFsIENvbXBsYWludHMiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiQ291bnQgb2YgQ29tcGxhaW50cyIpICsKICB0aGVtZV9lY29ub21pc3QoKQoKIyBGb3JlY2FzdCB0aGUgdGltZSBzZXJpZXMgdXNpbmcgdGhlIEFSSU1BIG1vZGVsCmFyaW1hX21vZGVsIDwtIGF1dG8uYXJpbWEodHNfZGF0YSkKdHNfZm9yZWNhc3QgPC0gZm9yZWNhc3QoYXJpbWFfbW9kZWwsIGggPSAzNjUqMykKCiMgUGxvdCB0aGUgb3JpZ2luYWwgdGltZSBzZXJpZXMgYW5kIGl0cyBmb3JlY2FzdApnZ3Bsb3QoKSArCiAgYWVzKHggPSBhbmltYWxfY29tcGxhaW50cyRkYXRlX3JlY2VpdmVkLCB5ID0gYW5pbWFsX2NvbXBsYWludHMkY291bnQgKSArCiAgZ2VvbV9saW5lKGNvbCA9ICJibHVlIikgKwogIGdlb21fbGluZShkYXRhID0gdHNfZm9yZWNhc3QkbWVhbiwgYWVzKHggPSBhcy5EYXRlKHRpbWUodHNfZm9yZWNhc3QkbWVhbikpLCB5ID0gdHNfZm9yZWNhc3QkbWVhbiksIGNvbCA9ICJyZWQiKSArCiAgZ2VvbV9yaWJib24oZGF0YSA9IHRzX2ZvcmVjYXN0LCBhZXMoeCA9IGFzLkRhdGUodGltZSh0c19mb3JlY2FzdCRtZWFuKSksIHltaW4gPSB0c19mb3JlY2FzdCRsb3dlclssMl0sIHltYXggPSB0c19mb3JlY2FzdCR1cHBlclssMl0pLCBmaWxsID0gImdyZXkiLCBhbHBoYSA9IDAuMykgKwogIHNjYWxlX3hfZGF0ZShkYXRlX2JyZWFrcyA9ICI2IG1vbnRocyIsIGRhdGVfbGFiZWxzID0gIiViICV5IikgKyAKICBsYWJzKHRpdGxlID0gIlRvd25zdmlsbGUgQ29tcGxhaW50IENhbGxzIiwKICAgICAgIHggPSAiVGltZSIsCiAgICAgICB5ID0gIk51bWJlciBvZiBDYWxscyIpICsKICB0aGVtZV9lY29ub21pc3QoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgdmp1c3QgPSAxLCBmYW1pbHkgPSAibW9ubyIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSA3KSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQodmp1c3QgPSAzLjIpLAogICAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJtb25vIiwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNCkpICsKICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSBhcy5EYXRlKCIyMDE0LTA2LTAxIiksIHhtYXggPSBhcy5EYXRlKCIyMDE0LTA4LTAxIiksIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCBmaWxsID0gImdyYXk3MCIsIGFscGhhID0gMC4zKSArCiAgYW5ub3RhdGUoInJlY3QiLCB4bWluID0gYXMuRGF0ZSgiMjAxNS0wNi0wMSIpLCB4bWF4ID0gYXMuRGF0ZSgiMjAxNS0wOC0wMSIpLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZmlsbCA9ICJncmF5NzAiLCBhbHBoYSA9IDAuMykgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IGFzLkRhdGUoIjIwMTYtMDYtMDEiKSwgeG1heCA9IGFzLkRhdGUoIjIwMTYtMDgtMDEiKSwgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsIGZpbGwgPSAiZ3JheTcwIiwgYWxwaGEgPSAwLjMKCmBgYApgYGB7cn0KIyBDcmVhdGUgYSB0aW1lIHNlcmllcyB3aXRoIGEgZnJlcXVlbmN5IG9mIDEyIChtb250aGx5IGRhdGEpCnRzX2RhdGEgPC0gdHMoYW5pbWFsX2NvbXBsYWludHMkY291bnQsIGZyZXF1ZW5jeSA9IDEyKQoKIyBGaXQgYSBzZWFzb25hbCBBUklNQSBtb2RlbCB0byB0aGUgdGltZSBzZXJpZXMKZml0IDwtIGF1dG8uYXJpbWEodHNfZGF0YSkKCiMgRm9yZWNhc3QgdGhlIG5leHQgMzYgcGVyaW9kcyAoMyB5ZWFycykKZm9yZWNhc3RfdmFsdWVzIDwtIGZvcmVjYXN0KGZpdCwgaCA9IDM2KQoKIyBQbG90IHRoZSBmb3JlY2FzdGVkIHZhbHVlcwpwbG90KGZvcmVjYXN0X3ZhbHVlcykKCmBgYAoKYGBge3J9CnRzX2RhdGEgPC0gdHMoZGF0YSwgc3RhcnQgPSBjKDIwMTQsIDEpLCBmcmVxdWVuY3kgPSAxMikKaW50ZXJ2YWwgPC0gdGltZSh0c19kYXRhKVsyXSAtIHRpbWUodHNfZGF0YSlbMV0KCmZpdCA8LSBhdXRvLmFyaW1hKHRzX2RhdGEsIHNlYXNvbmFsID0gVFJVRSkKZm9yZWNhc3RfdmFsdWVzIDwtIGZvcmVjYXN0KGZpdCwgaCA9IDM2LCB4cmVnID0gcmVncmVzc29ycywgbGFtYmRhID0gImF1dG8iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsID0gYyg4MCwgOTUpLCBmYW4gPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3QgPSBGQUxTRSwgcm9idXN0ID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEuYWN0aW9uID0gbmEucGFzcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvd21lYW4gPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZC5tZXRob2QgPSBjKCJhcmltYSIsICJldHMiLCAiYmF0cyIsICJ0YmF0cyIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSBOVUxMLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld3hyZWcgPSBOVUxMLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhbWJkYS5zZWFyY2ggPSAiYmFja3dhcmQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5iZXN0ID0gMSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZWVwLmZpdHRlZCA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFsbGVsID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbnVtLmNvcmVzID0gMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYXZlLmZvcmVjYXN0Lm1vZGVscyA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLikgCgoKYGBgCgpgYGB7cn0KbGlicmFyeShmb3JlY2FzdCkKCnRzX2RhdGEgPC0gYW5pbWFsX2NvbXBsYWludHMgJT4lIAogIGdyb3VwX2J5KGRhdGVfcmVjZWl2ZWQpICU+JSAKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JSAKICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogIGFzLm1hdHJpeC5kYXRhLmZyYW1lKCkKCnRzX2RhdGEgPC0gdHModHNfZGF0YSwgc3RhcnQgPSBjKDIwMTQsMSksIGZyZXF1ZW5jeSA9IDEyKQoKZml0IDwtIGF1dG8uYXJpbWEodHNfZGF0YSkKCmZvcmVjYXN0X3ZhbHVlcyA8LSBmb3JlY2FzdChmaXQsIGggPSAzNikKCmBgYAoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQoKdHNfZGF0YSA8LSBhbmltYWxfY29tcGxhaW50cyAlPiUKICBzZWxlY3QoZGF0ZV9yZWNlaXZlZCkgJT4lCiAgcHVsbCgpCgpmaXQgPC0gYXV0by5hcmltYSh0c19kYXRhKQoKZm9yZWNhc3RfdmFsdWVzIDwtIGZvcmVjYXN0KGZpdCwgaCA9IDM2KQpgYGAKCgoKCgoKCgo=